/*******************************************************************************
 * @note Copyright (C) 2011-2022， Shanghai Panchip Microelectronics Co., Ltd. 
 * @SPDX-License-Identifier: Apache-2.0
 * @history - V0.1, 2022-09-28
*******************************************************************************/
#include "pan3029_port.h"
#include "stimer.h"
#include "hardware.h"

#ifndef _CHIRPLAN_H_
#define _CHIRPLAN_H_

/*
 * Debug信息输出宏定义
 * _CHIRPLAN_DEBUG_LEVEL_LOW_输出关键日志
 * _CHIRPLAN_DEBUG_LEVEL_HIGH_输出较多日志
 */
//#define _CHIRPLAN_DEBUG_LEVEL_LOW_
//#define _CHIRPLAN_DEBUG_LEVEL_HIGH_


#define CHIRPLAN_FIFO_LEN			256   /*缓存大小*/

#define FSM_STATE_IDLE				0x00
#define FSM_STATE_WAIT_IRQ			0x01
#define FSM_STATE_CAD_TX_CHECK		0x02
#define FSM_STATE_CAD_TX_SEND		0x03
#define FSM_STATE_CAD_TX_DELAY		0x04
#define FSM_STATE_TX_HANDLE			0x05
#define FSM_STATE_RX_HANDLE			0x06

#define MAC_FRAME_JOIN_REQ			0x01
#define MAC_FRAME_JOIN_RESP			0x02
#define MAC_FRAME_UNCONFIRM_UP		0x03
#define MAC_FRAME_CONFIRM_UP		0x04
#define MAC_FRAME_UNCONFIRM_DOWN	0x05
#define MAC_FRAME_CONFIRM_DOWN		0x06
#define MAC_FRAME_CONFIRM_CONFIG	0x07
#define MAC_FRAME_SYNC_REQ			0x08
#define MAC_FRAME_SYNC_RESP			0x09

#define MAC_FRAME_LP_TRX			0x01
#define MAC_FRAME_LP_RX				0x02
#define MAC_FRAME_RUN				0x03

#define MAC_EVT_TX_CAD_NONE			0x00
#define MAC_EVT_TX_CAD_TIMEOUT		0x01
#define MAC_EVT_TX_CAD_ACTIVE		0x02

#define DEFAULT_FREQ_TABLE_NUM		16	/*需要是偶数*/
#define SELECT_FREQ_TABLE_NUM		8	/*需要是偶数*/

#define SEND_MSG_RETRY_TIME			3
#define SEND_MSG_CAD_RETRY_TIME		5
#define SEND_PACKET_MAX_TIME_MS		10000

#define MAC_FRAME_JOIN_REQ_LEN		10
#define MAC_FRAME_UP_PACK_OFFSET	10
#define MAC_FRAME_ACK_LEN			10

typedef void(*chirp_send_callback)(void);
typedef void(*chirp_recv_callback)(void);
typedef void(*chirp_join_callback)(void);
typedef void(*chirp_config_callback)(void);


typedef struct
{
	uint32_t one_chirp_time;				/*一个chirp信号持续时间，单位：us*/
	uint16_t cad_tx_join_time;				/*入网帧等待时间*/
	uint8_t  cad_tx_join_flag;				/*入网帧等待标志*/
	uint8_t  cad_tx_try_times;				/*CAD发射繁忙后，尝试次数累计计数*/
	uint8_t  cad_tx_timeout_flag;			
	uint8_t  send_msg_try_times;			/*重传时间*/
	uint8_t  need_ack;						/*ACK帧标志，内部使用*/
	uint8_t  rf_tx_busy_event;				/*RF发射保护，内部使用*/
	uint8_t  rf_wait_rx_ack_event;			/*等待ACK帧标志，内部使用*/
	uint8_t  rf_wait_tx_timer_event;		/*等待tx标志，内部使用*/
	ctimer_t stimer_chirplan_rxtimeout;		/*rx超时定时器*/
	ctimer_t stimer_chirplan_tx_delay_event;/*tx延时定时器*/
	ctimer_t stimer_chirplan_tx_send_event;	/*tx超时定时器*/
	ctimer_t stimer_chirplan_cad_event;	/*txcad超时定时器*/
	uint8_t fsm_state; 					/*状态机状态*/
} chirplan_proc_t;

/*!
 * ChirpLAN 数据结构
 */
typedef struct {
    /*point to the TX data buffer*/
    uint8_t TxBuff[CHIRPLAN_FIFO_LEN]__attribute__ ((aligned (4)));
    /*TX data buffer size*/
    uint8_t TxLen;
    /*point to the RX data buffer*/
    uint8_t RxBuff[CHIRPLAN_FIFO_LEN]__attribute__ ((aligned (4)));
    /*RX data buffer size*/
    uint8_t RxLen;
} chirp_app_data_t;

/*!
 * ChirpLAN 用户数据确认标记
 */
typedef enum {
    CHIRP_UNCONFIRMED_MSG   = 0,
    CHIRP_CONFIRMED_MSG     = !CHIRP_UNCONFIRMED_MSG
} chirp_confirm_t;

/*!
 * ChirpLAN 工作模式
 */
typedef enum {
    CHIRP_CLASS_A	= 0,   /*主动上报*/ 
    CHIRP_CLASS_B,   /*定时轮循*/
    CHIRP_CLASS_C,   /*全速运行*/

} chirp_workmode_t, net_class_t;

/*!
 * ChirpLAN 数据加密参数
 */
typedef struct {
    uint8_t enable;         /*加密使能*/ 
    uint8_t aes_key[16]__attribute__ ((aligned (4)));    /*aes密钥*/ 

} chirp_crypt_t;

/*!
 * ChirpLAN 终端ID参数
 */
typedef struct {
    uint8_t app_id;     
    uint32_t node_id;    
	uint32_t gw_net_id;
	
} chirp_netid_t;

/*!
 * ChirpLAN rf参数
 */
typedef struct {
    uint8_t ch;
    uint8_t sf;
    uint8_t bw;
    uint8_t cr;
    uint8_t crc;
    uint8_t tx_power;
    uint8_t ldr;
	uint8_t upcnt;
    uint16_t preambletime;
    uint16_t rxwindow;
	uint16_t rxsleeptime;
	
} chirp_rf_config_t;

/*!
 * ChirpLAN 参数结构体汇总，非入口
 */
typedef struct {
    chirp_crypt_t crypt;
    chirp_workmode_t workmode;
    chirp_rf_config_t rf_config;
    chirp_netid_t netid;
	chirp_confirm_t confirm;
	
} chirp_config_t;

/*!
 * ChirpLAN 工作状态
 */
typedef enum {
    CHIRP_STATE_IDLE,       /* 空闲 */
    CHIRP_STATE_UPLINK,     /* 上报数据 */
    CHIRP_STATE_DOWNLINK,   /* 下载数据 */
    CHIRP_STATE_RF_ERR, 
} chirplan_state_t;

/*!
 * ChirpLAN 入网标志
 */
typedef enum {
    CHIRP_RESET = 0,
    CHIRP_SET = !CHIRP_RESET,
} chirplan_join_status_t;

/*!
 * ChirpLAN 发送状态标志
 */
typedef enum { 
	CHIRP_SEND_IDLE = 0,     
    CHIRP_SEND_ING,    
    CHIRP_SEND_OK,      
    CHIRP_SEND_ERR,    
} chirplan_send_status_t;

/*!
 * ChirpLAN 接收状态标志
 */
typedef enum {
	CHIRP_RECV_IDLE = 0, 
    CHIRP_RECV_ING,    
    CHIRP_RECV_OK,      
    CHIRP_RECV_ERR,  
} chirplan_recv_status_t;

/*!
 * ChirpLAN rf状态标志
 */
typedef enum {
    CHIRP_RF_IDLE = 0,      
    CHIRP_RF_SEND_OK,    
    CHIRP_RF_RECV_OK,      
    CHIRP_RF_RECV_ERR,  
} chirplan_rf_status_t;

/*
 * ChirpLAN 操作返回状态
 */
typedef enum {
    CHIRPLAN_STATUS_OK = 0, 
    CHIRPLAN_STATUS_TIMEOUT,
    CHIRPLAN_STATUS_RF_ERR,
    CHIRPLAN_STATUS_SEND_ERR,
    CHIRPLAN_STATUS_RECV_ERR,
	CHIRPLAN_STATUS_RX_ID_ERR,
    CHIRPLAN_STATUS_OTHER_ERR,
} chirplan_status_t;

/*!
 * ChirpLAN 运行状态
 */
typedef struct {
	chirplan_state_t mac_state;
	chirplan_join_status_t join_status;
	chirplan_send_status_t send_status;
	chirplan_recv_status_t recv_status;
	chirplan_rf_status_t rf_status;
	
} chirp_all_status_t;

/*!
 * ChirpLAN 初始化参数结构体，参数总入口
 */
typedef struct {
    chirp_config_t config;
	chirp_app_data_t app_data;
	chirp_all_status_t all_status;

} chirp_t;
	
/*
 * ChirpLAN 接口函数
 * 用户调用
 */
typedef struct 
{
	/*
	 * 初始化，包含参数初始化，RF初始化，MAC层所有软状态初始化
	 * \param [IN] config 参数结构体，可以通过此结构向mac层下发参数，并通过此结构查询mac层当前的参数
	 * \param [IN] config_cb 回调函数，网关下发新的参数修改时，会回调此接口，可以为NULL（NULL表示不注册回调，已注册的回调仍会保留）
	 */
	chirplan_status_t	 ( *MacInit )(chirp_t *config, chirp_config_callback config_cb);
	/*
	 * 重新唤醒初始化，包含RF初始化。如果当前为CLASSB，还会打开CAD接收检测
	 */
    chirplan_status_t    ( *Wakeup )(void);
	/*
	* 获取ChirpLAN当前状态，IDLE,UP,DOWN,ERR
	 */
    chirplan_state_t ( *GetStatus )( void );
	/*
	 * 获取ChirpLAN发送状态，IDLE,ING,OK,ERR，如果使用发送回调，一般不需要额外查询此状态
	 */
    chirplan_send_status_t ( *GetSendStatus )( void );
	/*
	 * 获取ChirpLAN接收状态，IDLE,ING,OK,ERR，如果使用接收回调，一般不需要额外查询此状态
	 */
    chirplan_recv_status_t ( *GetRecvStatus )( void );
	/*
	 * 获取ChirpLAN入网状态
	 */
    chirplan_join_status_t ( *GetJoinStatus )( void );
	/*
	 * 配置参数，初始化之后，如果需要单独修改参数时使用
	 * \param [IN] txpower 发射功率，0~29
	 * \param [IN] ldr LDR控制，0~1
	 * \param [IN] crcOn CRC控制，0~1
	 * \param [IN] preambletime 前导码时间，单位ms
	 * \param [IN] rxwindow 超时接收窗口时间，A模式下有效，单位ms
	 * \param [IN] rxsleeptime 网关会下发这个参数，表示B模式的休眠时间
	 */
    chirplan_status_t    ( *SetRfConfig )( uint8_t txpower, uint8_t ldr,
                              uint8_t crcOn, uint16_t preambletime, uint16_t rxwindow, uint16_t rxsleeptime);
	/*
	 * 配置RATE参数，初始化之后，如果需要单独修改参数时使用
	 * \param [IN] sf SF，7~12
	 * \param [IN] bandwidth BW，6~9
	 * \param [IN] coderate  CR，1~4
	 */					  
    chirplan_status_t    ( *SetRate )( uint8_t sf, uint8_t bandwidth, uint8_t coderate);
	/*
	 * 发送数据，必须入网后才可发送，必须一包发完才能再发下一包
	 * \param [IN] app_data 本次要发送的数据，可以为NULL（NULL表示不发送数据，但是可以注册回调函数）
	 * \param [IN] confirmed 标志发送的数据是否需要回复
	 * \param [IN] send_cb 回调函数，数据发送结束，会回调此接口，可以为NULL（NULL表示不注册回调，已注册的回调仍会保留）
	 */					  
    chirplan_status_t    ( *Send )(chirp_app_data_t * app_data, chirp_confirm_t confirmed, chirp_send_callback send_cb);
	/*
	 * 发起入网
	 * \param [IN] join_cb 回调函数，入网完成后，会回调此接口，可以为NULL（NULL表示不注册回调，已注册的回调仍会保留）
	 */
    chirplan_status_t    ( *Join )(chirp_join_callback join_cb);
	/*
	* 注册接收回调函数，不会进入接收
	 * \param [IN] recv_cb 回调函数，接收到数据，会回调此接口，可以为NULL（NULL表示不注册回调，已注册的回调仍会保留）
	 */
    chirplan_status_t    ( *Recv )(chirp_recv_callback recv_cb);
	/*
	 * RF进入deepsleep，与Wakeup搭配使用
	 */
    chirplan_status_t    ( *Sleep )( void );
	/*
	 * RF进入deepsleep，并重置所有MAC层软状态，下次使用需要重新初始化
	 */
    chirplan_status_t    ( *StatusReset )( void );
	/*
	 * CLASSB进入接收，当B模式下，检测到CAD信号，即可调用。调用此接口后，如果已经注册了接收回调函数，会产生相关回调事件
	 */
    chirplan_status_t    ( *ClassBRx )( void );
	/*
	 * RF IRQ EVENT，MAC层调用，用来处理IRQ事件
	 */
    void ( *IrqProcess )( void );
}chirp_function_s;

/*
 * 获取ChirpLAN入网状态
 */
chirplan_join_status_t chirplan_get_join_status(void);

/*
 * 获取ChirpLAN发送状态
 */
chirplan_send_status_t chirplan_get_send_status(void);

/*
 * 获取ChirpLAN接收状态
 */
chirplan_recv_status_t chirplan_get_recv_status(void);

/*
 * 获取ChirpLAN当前状态
 */
chirplan_state_t chirplan_get_status(void);

/*
 * RF初始化，参数获取，状态复位
 */
chirplan_status_t chirplan_mac_init(chirp_t *config, chirp_config_callback config_cb);

/*
 * 唤醒函数
 */
chirplan_status_t chirplan_wakeup(void);

/*
 * RF参数设置
 */
chirplan_status_t chirplan_rf_para_config( uint8_t txpower, uint8_t ldr, uint8_t crcOn, uint16_t preambletime, uint16_t rxwindow, uint16_t rxsleeptime);
chirplan_status_t chirplan_rf_rate_config( uint8_t sf, uint8_t bandwidth, uint8_t coderate);

/*
 * 入网函数状态返回，入网成功与失败均会调用join_cb
 * 可调用chirplan_get_join_status查询入网状态
 */
chirplan_status_t chirplan_join(chirp_join_callback join_cb);

/*
 * 发送函数状态返回，发送成功与失败均会调用send_cb
 * 可调用chirplan_get_send_status查询发送状态
 */
chirplan_status_t chirplan_send(chirp_app_data_t * app_data, chirp_confirm_t confirmed, chirp_send_callback send_cb);

/*
 * 接收函数状态返回，入网成功与失败均会调用recv_cb
 * 可调用chirplan_get_recv_status查询接收状态
 */
chirplan_status_t chirplan_recv(chirp_recv_callback recv_cb);

/*
 * 将chirtiot相关软硬件进入休眠状态
 */
chirplan_status_t chirplan_sleep(void);

/*
* 将chirtiot所有相关软硬件复位，在模块工作模式切换时会用，RF进入deepsleep，mac状态复位
 */
chirplan_status_t chirplan_reset(void);

/*
 * chirtiot CLASSB 主动进入rx，仅在B模式下有效
 */
chirplan_status_t chirplan_classb_enter_rx(void);

/*
 * ChirpLAN mac层处理函数，放在main函数的主循环中
 */
void chirplan_mac_process(void);

extern chirp_t *mac_chirp;
extern chirp_function_s chirp_function ;

void chirplan_irq_handler(void);
void chirplan_irq_process( void );
uint32_t check_cad_rx_inactive(uint32_t one_chirp_time);
void check_cad_tx_inactive(void);
void show_mac_status( void );

#endif

